package controlador;

import modelo.Cliente;
import modelo.Producto;
import modelo.ProductoIngrediente;
import modelo.ProductoIngredienteDao;
import modelo.ProductoDao;
import modelo.Categoria;
import modelo.CategoriaDao;
import modelo.IngredienteDao;
import modelo.Ingrediente;
import vista.VentanaProducto;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableColumn;
import javax.swing.DefaultCellEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowListener;
import java.awt.event.KeyListener;
import java.awt.event.FocusListener;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

import vista.Mensaje;

public class ControladorProducto extends WindowAdapter implements ActionListener,KeyListener,ItemListener,MouseListener,FocusListener
{
	private VentanaProducto ventana;
	private ControladorPrincipal controladorPrincipal;
	private ProductoDao productoDao;
	private CategoriaDao categoriaDao;
	private IngredienteDao ingredienteDao;
	private ArrayList<Producto> productos;
	private ArrayList<Categoria> categorias;
	private boolean guardando;
	private TableModel modeloTabla;
	
    public ControladorProducto(ControladorPrincipal controladorPrincipal)
    {
    	this.controladorPrincipal= controladorPrincipal;
    	ventana= new VentanaProducto();
    	productoDao= new ProductoDao();
        categoriaDao= new CategoriaDao();
        ingredienteDao = new IngredienteDao();
        
        productos= new ArrayList<Producto>();
        categorias= new ArrayList<Categoria>();
        guardando=false;
        
        modeloTabla= new DefaultTableModel();
    	
    	ventana.addListener((WindowListener)this);
    	ventana.addListener((ActionListener)this);
    	ventana.addListener((FocusListener)this);
    	ventana.addListener((KeyListener)this);
    	
    	ventana.setVisible(true);
    }

    private void guardar()
	{
		
		try
		{
		  Producto producto= new Producto(ventana.getCodProducto(),
				             categoriaDao.getCategoriaNombreCorto(ventana.getCategoria()),
				             ventana.getNombreCorto(), ventana.getNombreLargo(),ventana.getPorcGanancia());
		  
		  boolean valido=true;
		  if (modeloTabla instanceof ModeloTablaModificable)
		  {
			  
			  Ingrediente ingrediente;
			  
			  for (int i=0; i < modeloTabla.getRowCount(); ++i)
              {
                   if ((Boolean)modeloTabla.getValueAt(i,0))
                   {
                	   
                	  ventana.asignarValoresEdicionTabla(i, 6); 
                	   
                      ingrediente= ingredienteDao.getIngrediente((String)modeloTabla.getValueAt(i, 1));  	   
      
                      double cantidad= 0.0;
                      
                      try
                      {
                    	 
                    	  cantidad = Double.parseDouble((String)modeloTabla.getValueAt(i, 6));
                    	  producto.agregarProductoIngrediente(new ProductoIngrediente(ingrediente,cantidad));
                      }
                      catch(NumberFormatException e)
                      {
                    	  
                    	  valido= false;
                    	  break;
                      }
                     
                   }
              }
		  }
		  
		 
		  
	      if (producto.validar() && valido)
	      {	  
	    	    
	    		 
			     if (!productoDao.consultarProducto(producto))
			     {
				     if (!productoDao.consultarProductoNombreCorto(producto))
				     {	 
			    	     if (productoDao.isEliminado(producto))
				    	 {
				    		 if (Mensaje.mostrarConfirmacion("El Producto Habia sido Eliminado Previamente\nDesea Reactivarlo?"))
				    		 {		 
				    		   if (productoDao.activarProducto(producto))
				    			  Mensaje.mostrarInformacion("El Producto se ha Activado con Exito");
				    		   else
				    			  Mensaje.mostrarError("Error al Activar Producto");
				    		 }  
				    	 } 
				    	 else
				    	 {
				    		 if (Mensaje.mostrarConfirmacion("Desea Registrar a este Producto?"))
				    		 {		 
				    		   if (productoDao.registrarProducto(producto))
				    			  Mensaje.mostrarInformacion("El Producto se ha registrado con Exito");
				    		   else
				    			 Mensaje.mostrarError("Error al Registrar Producto");
				    		 } 
				    	 }
				     }
				     else
				     {
				    	 Mensaje.mostrarError("Ya existe un Producto con el mismo Nombre Corto en la misma Categoria!!!");
				    	 
				     }
				     
			     }
			     else
			     {
			    	 Mensaje.mostrarError("El Producto ya fue Registrado!!!");
			     } 	 
	    	 
	      }
	      else
	      {	  
	         Mensaje.mostrarError("La Informacion del Producto es invalida!!!");
	         
	      }
	      
	      iniciarInfo();
		  
		}
		catch(Exception e)
		{
			iniciarInfo();
			Mensaje.mostrarError(e.getMessage());
		}
		
	}
    
    private void modificar()
	{  
		try
		{
		
			 Producto producto= new Producto(ventana.getCodProducto(),categoriaDao.getCategoriaNombreCorto(ventana.getCategoria()),ventana.getNombreCorto(),ventana.getNombreLargo(),ventana.getPorcGanancia());
			 List<ProductoIngrediente> lista= new ProductoIngredienteDao().getProductosIngredientes(producto);
			 producto.sustituirProductosIngredientes(lista);
			 
	      if (producto.validar())
	      {	  
		     if (productoDao.consultarProducto(producto))
		     {
		    	 if (productoDao.consultarProductoNombreCorto(producto))
		    	 {
			    	 if (Mensaje.mostrarConfirmacion("Desea Modificar la Informacion de este Producto?"))
			    	 {
			    		
			    		if (productoDao.actualizarProducto(producto))
			    			Mensaje.mostrarInformacion("El Producto se ha Modificado con Exito");
			    		else
			    		   Mensaje.mostrarError("Error al Modificar Producto");
			    		 
			    	 }
		    	 }
		    	 else
		    	 {
		    		 Mensaje.mostrarError("Ya existe un Producto con el mismo Nombre Corto en la misma Categoria!!!");
		    	 }
		     }
		     else
		     {
		    	 Mensaje.mostrarError("El Producto no ha sido Registrado!!!");
		     } 	 
		     
	      }
	      else
	      {	  
	         Mensaje.mostrarError("La Informacion del cliente es invalida!!!");
	         
	      }
	      
	      iniciarInfo();
		  
		}
		catch(Exception e)
		{
			Mensaje.mostrarError(e.getMessage());
		}
	}
    
    private void eliminar()
	{
	  
		try
		{
			 Producto producto= new Producto(ventana.getCodProducto(),categoriaDao.getCategoriaNombreCorto(ventana.getCategoria()),ventana.getNombreCorto(),ventana.getNombreLargo(),ventana.getPorcGanancia());
			 List<ProductoIngrediente> lista= new ProductoIngredienteDao().getProductosIngredientes(producto);
			 producto.sustituirProductosIngredientes(lista);
			
	     
		    if (productoDao.consultarProducto(producto))
		    {
		    	if (!productoDao.isDependiente(producto))
		    	{		
		    	  if (Mensaje.mostrarConfirmacion("Desea Eliminar a este Producto?"))
		    	  {
		    		
		    		 if (productoDao.eliminarProducto(producto))
		    		 	Mensaje.mostrarInformacion("El Producto se ha Eliminado con Exito");
		    		 else
		    		    Mensaje.mostrarError("Error al Eliminar Producto");
		    		 
		    	   }
		    	}
		    	else
		    		Mensaje.mostrarError("El Producto No Puede ser Eliminado\nExiste Informacion Relacionada con este!!!");
		    }
		    else
		    {
		    	 Mensaje.mostrarError("El Producto ya se ha Eliminado!!!");
		    } 	 
		    
	    
	      
	      iniciarInfo();
		  
		}
		catch(Exception e)
		{
			Mensaje.mostrarError(e.getMessage());
		}
	}
	
    
    private void actualizarVentana(ArrayList<ProductoIngrediente> productosIngredientes,boolean editable)
    {
		
    	if (!productosIngredientes.isEmpty())
    	{	
    		
		    //Para hacer No editable la tabla
			if (!editable)
		    {
			   
				Object[] encabezado= {"Codigo","Nombre Corto","Nombre Largo","Unid Medida","Costo","Cantidad"};
				
				Object[][] data= new Object[productosIngredientes.size()][encabezado.length];
				
				int i=0;
	
	            Iterator<ProductoIngrediente> iterador= productosIngredientes.iterator();
	
	            ProductoIngrediente productoIng;
	            
	            
	            while (iterador.hasNext())
	            {	
	            	productoIng= iterador.next();
	                data[i][0]= productoIng.getIngrediente().getCodigo();
	                data[i][1]= productoIng.getIngrediente().getNombreCorto();
	                data[i][2]= productoIng.getIngrediente().getNombreLargo();
	                data[i][3]= productoIng.getIngrediente().getUnidadMedida();
	                data[i][4]= productoIng.getIngrediente().getCosto();
	                data[i][5]= productoIng.getCantidad();
	                ++i;
	            }
		        modeloTabla= new ModeloTablaEstatico(data,encabezado);
		        ventana.asignarDatosTabla(modeloTabla);
		    }
			else //Para hacer editable la tabla
			{
	            String[] encabezado= {"","Codigo","Nombre Corto","Nombre Largo","Unid Medida","Costo","Cantidad"};
				
				Object[][] data= new Object[productosIngredientes.size()][encabezado.length];
				javax.swing.JTextField txtF= new javax.swing.JTextField();
				txtF.addKeyListener(new EscuchadorInterno());
				
				Iterator<ProductoIngrediente> iterador= productosIngredientes.iterator();
	
	            ProductoIngrediente productoIng;
	            
	            int i=0;
	            
	            while (iterador.hasNext())
	            {	
	            	productoIng= iterador.next();
	            	data[i][0]= new Boolean(false);
	                data[i][1]= productoIng.getIngrediente().getCodigo();
	                data[i][2]= productoIng.getIngrediente().getNombreCorto();
	                data[i][3]= productoIng.getIngrediente().getNombreLargo();
	                data[i][4]= productoIng.getIngrediente().getUnidadMedida();
	                data[i][5]= productoIng.getIngrediente().getCosto();
	                data[i][6]= "0.0";
	                ++i;
	            }
				
				
				
				modeloTabla= new ModeloTablaModificable(data,encabezado);
			    ventana.asignarDatosTabla(modeloTabla);
				 
		      	TableColumn marcaVerificacion= ventana.getTableColumnModel().getColumn(0);
				TableColumn cantidad= ventana.getTableColumnModel().getColumn(6);
					
				cantidad.setCellEditor(new DefaultCellEditor(txtF));
				marcaVerificacion.setPreferredWidth(5);
				
			}
    	} 
		
    }
    
    
    private void actualizarVentana(Producto producto)
    {
    	try
    	{
	    	ArrayList<String> listaNombres= new ArrayList<String>();
	    	
	    	for (Categoria categoria:categorias)
	    	{
	    		listaNombres.add(categoria.getNombreCorto());
	    	}		
	    	
	    	if (!listaNombres.isEmpty())
	    	{
	    		ventana.actualizarCombo(listaNombres.toArray());
	    	
		    	if (producto!=null)
		    	{  		
		    		ventana.actualizarInfo(producto.getCodigo(), producto.getNombreCorto(), 
		    				               producto.getNombreLargo(), producto.getPorcGanancia());
		    		
		    		ventana.actualizarInfoCategoria(producto.getCategoria().getNombreCorto());
		    		
		    		
		    	}
		    	else
		    	{
		    		ventana.actualizarInfo("", "", 
				               "", 0.0f);
		    	}
	    	}
	    	else
	    	{
	    		ventana.actualizarInfo("", "","", 0.0f);
	    		ventana.deshabilitarBotonActualizar("Guardar");
	    		ventana.deshabilitarBotonActualizar("Modificar");
	    		ventana.deshabilitarBotonActualizar("Eliminar");
	    		ventana.deshabilitarBotonActualizar("Cancelar");
	    	}
    	}
    	catch(Exception e)
    	{
    		Mensaje.mostrarInformacion(e.getMessage());
    	}
    	
    }
    
    public void iniciarInfo()
    {
    	try
    	{
    		
    		if (!productos.isEmpty())	
    			productos.clear();
    		  
    		 productos.addAll(productoDao.consultarProductosActivos());
    		
    		 if(!categorias.isEmpty())
    			 categorias.clear();
    		 
    		 categorias.addAll(categoriaDao.consultarCategorias());
    		
    		actualizarVentana(null);
    		
    		 modeloTabla= new DefaultTableModel();
    		 ventana.asignarDatosTabla(modeloTabla);
    		
    		ventana.deshabilitarBotonActualizar("Guardar");
    		ventana.deshabilitarBotonActualizar("Modificar");
    		ventana.deshabilitarBotonActualizar("Eliminar");
    		ventana.deshabilitarBotonActualizar("Cancelar");
    		 
    		
    	}
    	catch(Exception e)
    	{
    		Mensaje.mostrarError(e.getMessage());
    		
			controladorPrincipal.visualizarVentana();
			ventana.setVisible(false);
			ventana.dispose();
    	}
    }
    
    
    public void windowClosing(WindowEvent event)
	{
		controladorPrincipal.visualizarVentana();
		ventana.setVisible(false);
		ventana.dispose();
	}
    
    public void windowOpened(WindowEvent event)
	{
		iniciarInfo();
	}


	@Override
	public void itemStateChanged(ItemEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void keyTyped(KeyEvent evt) 
	{
		if (evt.getSource() instanceof javax.swing.JTextField)
		{
			javax.swing.JTextField txt= (javax.swing.JTextField) evt.getSource();
			evt.setKeyChar(Character.toUpperCase(evt.getKeyChar()));
			if (txt.getName().equalsIgnoreCase("txtCodProducto"))
			{
				
				
				if (ventana.getCodProducto().length()==Producto.MAXCODIGO)
					evt.setKeyChar(Character.MIN_VALUE);
				
			}
			else if ((txt.getName().equalsIgnoreCase("txtNombreCorto")))
			{
				if (ventana.getNombreCorto().length()==Producto.MAXNOMBRECORTO)
					evt.setKeyChar(Character.MIN_VALUE);
				else
				{
					if (guardando)
					{
					    ventana.habilitarBotonActualizar("Guardar");
					    ventana.deshabilitarBotonActualizar("Modificar");
					    ventana.deshabilitarBotonActualizar("Eliminar");
					}
				    else
					{
						 ventana.deshabilitarBotonActualizar("Guardar");
						 ventana.habilitarBotonActualizar("Modificar");
						 ventana.deshabilitarBotonActualizar("Eliminar");
					}
					ventana.habilitarBotonActualizar("Cancelar");
				}
			}
			else if (txt.getName().equalsIgnoreCase("txtNombreLargo"))
			{
				if ( ventana.getNombreLargo().length()==Producto.MAXNOMBRELARGO)
					evt.setKeyChar(Character.MIN_VALUE);
				else
				{
					if (guardando)
					{
					    ventana.habilitarBotonActualizar("Guardar");
					    ventana.deshabilitarBotonActualizar("Modificar");
					    ventana.deshabilitarBotonActualizar("Eliminar");
					}
				    else
					{
						 ventana.deshabilitarBotonActualizar("Guardar");
						 ventana.habilitarBotonActualizar("Modificar");
						 ventana.deshabilitarBotonActualizar("Eliminar");
					}
					ventana.habilitarBotonActualizar("Cancelar");
				}
			}
			else if (txt.getName().equalsIgnoreCase("txtPorcGanancia"))
			{		
				if ((char)KeyEvent.VK_BACK_SPACE!= evt.getKeyChar() && !Character.isDigit(evt.getKeyChar()) && '.'!=evt.getKeyChar())
			         evt.setKeyChar(Character.MIN_VALUE);
				else
				{
					
					if (guardando)
					{
					    ventana.habilitarBotonActualizar("Guardar");
					    ventana.deshabilitarBotonActualizar("Modificar");
					    ventana.deshabilitarBotonActualizar("Eliminar");
					}
				    else
					{
						 ventana.deshabilitarBotonActualizar("Guardar");
						 ventana.habilitarBotonActualizar("Modificar");
						 ventana.deshabilitarBotonActualizar("Eliminar");
					}
					ventana.habilitarBotonActualizar("Cancelar");
				}
				
			}
			
			
			
		}
		
		
		
	}


	@Override
	public void actionPerformed(ActionEvent e)
	{
		if (e.getSource() instanceof javax.swing.JButton)
		{
			
			if (e.getActionCommand().equalsIgnoreCase("Guardar"))
				guardar();
			else if(e.getActionCommand().equalsIgnoreCase("Modificar"))
				modificar();
			else if(e.getActionCommand().equalsIgnoreCase("Eliminar"))
				eliminar();
			else if (e.getActionCommand().equalsIgnoreCase("Cancelar"))
			{
				iniciarInfo();
			}		
		    else if (e.getActionCommand().equalsIgnoreCase("Salir"))
			{
				controladorPrincipal.visualizarVentana();
				ventana.setVisible(false);
				ventana.dispose();
			}
			
		
		}		
		
	}


	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void focusGained(FocusEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void focusLost(FocusEvent evt) 
	{
		if (evt.getSource() instanceof javax.swing.JTextField)
		{
			
			if (!categorias.isEmpty())
			{		
				Producto producto= new Producto(ventana.getCodProducto(),categorias.get(0),"","",0.0f);
				
					
				try
				{
				  
				  /*Actualiza el ArrayList con la base de datos*/
				  if (!productos.containsAll(productoDao.consultarProductosActivos()))
				  {
					  if (!productos.isEmpty())	
							productos.clear();
						  
					  productos.addAll(productoDao.consultarProductosActivos());
                     
				  } 
				 /********************************************/
				 	
				  if (productos.contains(producto))
				  {
					 				 
					 ArrayList<ProductoIngrediente> listaP= new ArrayList<ProductoIngrediente>();
					 Iterator <ProductoIngrediente> it= productos.get(productos.indexOf(producto)).getIterador();
					 
					 while (it.hasNext())
						 listaP.add(it.next());
					
					
					 
					 actualizarVentana(productos.get(productos.indexOf(producto)));
					 actualizarVentana(listaP,false);
					 ventana.asignarPrecioTotal(productos.get(productos.indexOf(producto)).getPrecioVenta());
					 
					 ventana.deshabilitarBotonActualizar("Guardar");
					 ventana.habilitarBotonActualizar("Eliminar");
					 ventana.deshabilitarBotonActualizar("Modificar");
					 ventana.deshabilitarBotonActualizar("Cancelar");
					 
					 guardando=false;
					 
				  }
				  else
				  {
					 ArrayList<ProductoIngrediente> listaP= new ArrayList<ProductoIngrediente>();
					 List<Ingrediente> listaI= ingredienteDao.consultarIngredientesActivos();
					 
					 for (Ingrediente ing:listaI)
					 {
					    listaP.add(new ProductoIngrediente(ing,0.0)); 	 
					 }	
					 
					 
					 actualizarVentana(producto);
					 actualizarVentana(listaP,true);
					 
					 ventana.limpiarTextos();
					 ventana.habilitarBotonActualizar("Guardar");
					 ventana.habilitarBotonActualizar("Cancelar");
					 ventana.deshabilitarBotonActualizar("Modificar");
					 ventana.deshabilitarBotonActualizar("Eliminar");
					 
					 guardando= true;
				  }
				  
				  
				}
				catch(Exception e)
				{
					Mensaje.mostrarError(e.getMessage());
				}
			}		
				
		}
		
		
	}
	
	private class ModeloTablaEstatico extends DefaultTableModel
	{
		

	    public ModeloTablaEstatico(Object[][] data, Object[] columnNames) 
	    {
		        super(data, columnNames);
	    }
  


		    @Override
		 public boolean isCellEditable(int row,int col)
         {
	          return false;
	
         }
		
	}
	
	private class ModeloTablaModificable extends AbstractTableModel
	{
		 
		   private  Object[][] info;
		   private  String[] titulo;

		   ModeloTablaModificable(Object[][] data,String[] titulos)
		   {
		         info= data;
		         titulo= titulos;
		         
		   }     
		   

		    public int getRowCount() {
		        return info.length;
		    }

		    public int getColumnCount() {
		       return titulo.length;
		    }

		    public Object getValueAt(int rowIndex, int columnIndex) {
		        return info[rowIndex][columnIndex];
		    }

		    public Class<? extends Object> getColumnClass(int c) {
		            return info[0][c].getClass();
		        }

		    public String getColumnName(int col) {
		            return titulo[col];
		        }


		    public boolean isCellEditable(int row,int col)
		    {
		        boolean editable= false;
		        if (col==0  || col==6)
		            editable= true;
		        return editable;
		    }

		    public void setValueAt(Object value, int row, int col)
		    {
		    	if (col==6 && (Boolean)info[row][0])
		    	{
		    		try
		    		{
		              double cantidad= Double.parseDouble((String)value);
		              double costo= (Double)info[row][5];
		              double porcGanancia= ventana.getPorcGanancia();
		            
		              ventana.asignarPrecioTotal(Math.floor(ventana.getPrecioTotal() + (cantidad * costo) + ((porcGanancia * cantidad * costo)/100)));
		    		}
		    		catch(NumberFormatException e){}
		    	}
		        info[row][col]= value;
		        fireTableCellUpdated(row, col);
		    }
		
	}
	
	private class EscuchadorInterno implements KeyListener
	{

		@Override
		public void keyPressed(KeyEvent evt) {
			
			
		}

		@Override
		public void keyReleased(KeyEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void keyTyped(KeyEvent evt) {
			if (!(Character.isDigit(evt.getKeyChar()) || '.'==evt.getKeyChar()))		
	               evt.setKeyChar(Character.MIN_VALUE);
			
		}
		
	}
}
